//
//  MKAPITaskWatiTestCase.m
//  MKAPITests
//
//  Created by 苏尚进 on 2022/8/15.
//  Copyright © 2022 moon. All rights reserved.
//

#import "MKAPITaskWatiTestCase.h"
#import "NSTimer+MKAPITest.h"
#import "MKAPITestTimerAPIBase.h"
#import <MKAPI/MKAPI.h>


@interface __MKAPITaskWatiTestCase_APIBaseA : MKAPITestTimerAPIBase
@end
@interface __MKAPITaskWatiTestCase_APITestA : MKAPITestTimerAPIBase
@end
@interface __MKAPITaskWatiTestCase_APITestB : MKAPITestTimerAPIBase
@end
@interface __MKAPITaskWatiTestCase_APITestC : MKAPITestTimerAPIBase
@end
@interface __MKAPITaskWatiTestCase_APITestD : MKAPITestTimerAPIBase
@end
@interface __MKAPITaskWatiTestCase_APITestE : MKAPITestTimerAPIBase
@end

@interface __MKAPITaskWatiTestCase_APITestDependance : MKAPITestTimerAPIBase
@end


@implementation __MKAPITaskWatiTestCase_APITestA
- (void)doRunTask{
    __MKAPITaskWatiTestCase_APITestE *e1 = [[__MKAPITaskWatiTestCase_APITestE alloc] initWithDuration:0.4];
    __MKAPITaskWatiTestCase_APITestC *c1 = [[__MKAPITaskWatiTestCase_APITestC alloc] init];
    __MKAPITaskWatiTestCase_APITestD *d1 = [[__MKAPITaskWatiTestCase_APITestD alloc] initWithDuration:0.4];
    __MKAPITaskWatiTestCase_APITestB *b1 = [[__MKAPITaskWatiTestCase_APITestB alloc] init];
    [b1 cancel];
    MKAPITestTimerAPISuccess *s1 = [[MKAPITestTimerAPISuccess alloc] init];
    [self waitTasks:@[e1,c1,d1,b1,s1] withCompletion:^(NSArray<__kindof MKAPITask *> * _Nonnull tasks, BOOL success, NSError * _Nullable error) {
        if(success){
            [self doRunTimerTask];
        }else{
            [self completeWithError:error];
        }
    }];
}
- (void)doCancel{
    [super doCancel];
    [self cancelWaittingTasks];
}
@end
@implementation __MKAPITaskWatiTestCase_APITestB

@end
@implementation __MKAPITaskWatiTestCase_APITestC

@end
@implementation __MKAPITaskWatiTestCase_APITestD

@end
@implementation __MKAPITaskWatiTestCase_APITestE
- (void)doRunTask{
    __MKAPITaskWatiTestCase_APITestC *c1 = [[__MKAPITaskWatiTestCase_APITestC alloc] initWithDuration:0.2];
    __MKAPITaskWatiTestCase_APITestD *d1 = [[__MKAPITaskWatiTestCase_APITestD alloc] initWithDuration:0.2];
    __MKAPITaskWatiTestCase_APITestB *b1 = [[__MKAPITaskWatiTestCase_APITestB alloc] init];
    [b1 cancel];
    MKAPITestTimerAPISuccess *s1 = [[MKAPITestTimerAPISuccess alloc] init];
    [self waitTasks:@[c1,d1,b1,s1] withCompletion:^(NSArray<__kindof MKAPITask *> * _Nonnull tasks, BOOL success, NSError * _Nullable error) {
        if(success){
            __MKAPITaskWatiTestCase_APITestB *b2 = [[__MKAPITaskWatiTestCase_APITestB alloc] initWithDuration:0.2];
            [self waitTasks:@[b2] withCompletion:^(NSArray<__kindof MKAPITask *> * _Nonnull tasks, BOOL success, NSError * _Nullable error) {
                if(success){
                    [self doRunTimerTask];
                }else{
                    [self completeWithError:error];
                }
            }];
        }else{
            [self completeWithError:error];
        }
    }];
}
- (void)doCancel{
    [super doCancel];
    [self cancelWaittingTasks];
}
@end

@implementation __MKAPITaskWatiTestCase_APITestDependance
- (void)doRunTask{
    __MKAPITaskWatiTestCase_APITestB *b1 = [[__MKAPITaskWatiTestCase_APITestB alloc] initWithDuration:1];
    __MKAPITaskWatiTestCase_APITestB *b2 = [[__MKAPITaskWatiTestCase_APITestB alloc] initWithDuration:1.5];
    __MKAPITaskWatiTestCase_APITestB *b3 = [[__MKAPITaskWatiTestCase_APITestB alloc] initWithDuration:2];
    @MKAPI_WEAKIFY(self);
    [self waitTasks:@[b1,b2,b3] withCompletion:^(NSArray<__kindof MKAPITask *> * _Nonnull tasks, BOOL success, NSError * _Nullable error) {
        @MKAPI_NORMALIZE(self);
        if(success){
            [self doRunTimerTask];
        }else{
            [self completeWithError:error];
        }
    } ];
}
- (void)doCancel{
    [super doCancel];
    [self cancelWaittingTasks];
}
@end

@implementation MKAPITaskWatiTestCase
- (void)test___MKAPITaskWatiTestCase_APITestDependance{
    NSMutableArray<XCTestExpectation *> *expectations = [[NSMutableArray alloc] init];
    __MKAPITaskWatiTestCase_APITestDependance *apiA = [[__MKAPITaskWatiTestCase_APITestDependance alloc] init];
    [apiA addProgressHandler:^(__kindof MKAPITask * _Nonnull task, NSProgress * _Nonnull progress) {
        NSLog(@"progress percent:%.2f,%@",progress.mkapi_progressPercent,progress);
        if(progress.completedUnitCount>progress.totalUnitCount){
            XCTAssertFalse(progress.completedUnitCount>progress.totalUnitCount,@"progress.completedUnitCount>progress.totalUnitCount");
        }
    }];
    [expectations addObject:[apiA createBeginExpectationsWithTestCase:self]];
    [expectations addObject:[apiA createProgressExpectationsWithTestCase:self]];
    [expectations addObject:[apiA createCompletionExpectationsWithTestCase:self]];
    
    [apiA run];
    
    [self waitForExpectations:expectations timeout:apiA.duration*5];
}
- (void)test_TaskWait{
    NSMutableArray<XCTestExpectation *> *expectations = [[NSMutableArray alloc] init];
    __MKAPITaskWatiTestCase_APITestA *apiA = [[__MKAPITaskWatiTestCase_APITestA alloc] init];
    [expectations addObject:[apiA createBeginExpectationsWithTestCase:self]];
    [expectations addObject:[apiA createProgressExpectationsWithTestCase:self]];
    [expectations addObject:[apiA createCompletionExpectationsWithTestCase:self]];
    for (MKAPITask *a in apiA.waittingTasks) {
        if(![a isKindOfClass:[MKAPITestTimerAPIBase class]]){
            continue;
        }
        MKAPITestTimerAPIBase *api = (MKAPITestTimerAPIBase *)a;
        [expectations addObject:[api createCompletionExpectationsWithTestCase:self]];
    }
    
    [apiA run];
    [self waitForExpectations:expectations timeout:apiA.duration*5];
}
- (void)test_TaskWaitCancel{
    NSMutableArray<XCTestExpectation *> *expectations = [[NSMutableArray alloc] init];
    __MKAPITaskWatiTestCase_APITestA *apiA = [[__MKAPITaskWatiTestCase_APITestA alloc] init];
    apiA.completionExpectation = [self expectationWithDescription:[NSString stringWithFormat:@"%@.completionExpectation",NSStringFromClass(apiA.class)]];
    apiA.cancelExpectation = [self expectationWithDescription:[NSString stringWithFormat:@"%@.cancelExpectation",NSStringFromClass(apiA.class)]];
    [apiA addProgressHandler:^(__kindof MKAPITask * _Nonnull task, NSProgress * _Nonnull progress) {
        XCTAssertFalse(progress.completedUnitCount>progress.totalUnitCount,@"progress.completedUnitCount>progress.totalUnitCount");
    }];
    [apiA run];
    NSTimeInterval cancelDuration = apiA.duration/2;
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(cancelDuration * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        [apiA cancel];
    });
    [expectations addObject:apiA.completionExpectation];
    [expectations addObject:apiA.cancelExpectation];
    for (MKAPITask *a in apiA.waittingTasks) {
        if(![a isKindOfClass:[MKAPITestTimerAPIBase class]]){
            continue;
        }
        MKAPITestTimerAPIBase *api = (MKAPITestTimerAPIBase *)a;
        api.completionExpectation = [self expectationWithDescription:[NSString stringWithFormat:@"%@.completionExpectation",NSStringFromClass(api.class)]];
        [expectations addObject:api.completionExpectation];
        if(api.duration>cancelDuration){
            api.cancelExpectation = [self expectationWithDescription:[NSString stringWithFormat:@"%@.cancelExpectation",NSStringFromClass(api.class)]];
            [expectations addObject:api.cancelExpectation];
        }
    }
    [self waitForExpectations:expectations timeout:apiA.duration*5];
}
- (void)test_NSProgress{
    NSProgress *progressA = [NSProgress progressWithTotalUnitCount:100];
    NSProgress *p1 = [NSProgress progressWithTotalUnitCount:100];
    NSProgress *p2 = [NSProgress progressWithTotalUnitCount:100];
    NSProgress *p12 = [NSProgress progressWithTotalUnitCount:0];
    [p12 addChild:p1 withPendingUnitCount:p1.totalUnitCount];
    p12.totalUnitCount += p1.totalUnitCount;
    [p12 addChild:p2 withPendingUnitCount:p2.totalUnitCount];
    p12.totalUnitCount += p2.totalUnitCount;
    
    progressA.totalUnitCount += p12.totalUnitCount;
    [progressA addChild:p12 withPendingUnitCount:p12.totalUnitCount];
    NSLog(@"p:%@",progressA.mkapi_description);
    for (int i=1; i<=100; i++) {
        p1.completedUnitCount = i;
        NSLog(@"p:%@",progressA.mkapi_description);
    }
    NSLog(@"p:%@",progressA.mkapi_description);
    for (int i=1; i<=100; i++) {
        p2.completedUnitCount = i;
        NSLog(@"p:%@",progressA.mkapi_description);
    }
    NSLog(@"p:%@",progressA.mkapi_description);
    for (int i=1; i<=100; i++) {
        progressA.completedUnitCount ++;
        NSLog(@"p:%@",progressA.mkapi_description);
    }
    NSLog(@"p:%@",progressA.mkapi_description);
}
@end
